package com.siaron.framework.eventbus.autoconfigure;

import com.google.common.base.Splitter;
import com.siaron.framework.eventbus.model.FunctionInfo;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.stream.config.BindingServiceProperties;
import org.springframework.cloud.stream.function.StreamFunctionProperties;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author xielongwang
 * @create 2021/7/19 4:17 下午
 * @email siaron.wang@gmail.com
 * @description 配置扫描到的函数和binding
 */
public class BindingServicePropertiesProcessor implements BeanPostProcessor {

    private static final String FUNCTION_DELIMITER = ";";

    private final ConfigurableEnvironment configurableEnvironment;

    public BindingServicePropertiesProcessor(ConfigurableEnvironment configurableEnvironment) {
        this.configurableEnvironment = configurableEnvironment;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof BindingServiceProperties) {
            BindingServiceProperties bindingServiceProperties = (BindingServiceProperties) bean;
            Map<String, FunctionInfo> fun = BindingCache.getFun();
            for (Map.Entry<String, FunctionInfo> entry : fun.entrySet()) {
                bindingServiceProperties.getBindings().put(entry.getKey(), entry.getValue().getBindingProperties());
            }
            return bindingServiceProperties;
        }

        //stream function Definition writer
        if (bean instanceof StreamFunctionProperties) {
            StreamFunctionProperties functionProperties = (StreamFunctionProperties) bean;
            String definition = functionProperties.getDefinition();
            Set<String> definitionSet = BindingCache.getFun().values().stream().map(FunctionInfo::getFunName).filter(Objects::nonNull).collect(Collectors.toSet());
            if (definition != null) {
                Iterable<String> splitFun = Splitter.on(FUNCTION_DELIMITER).trimResults()
                        .omitEmptyStrings()
                        .split(definition);
                for (String sf : splitFun) {
                    definitionSet.add(sf);
                }
            }
            functionProperties.setDefinition(String.join(FUNCTION_DELIMITER, definitionSet));
            return functionProperties;
        }

        return bean;
    }
}
